package com.doubao.hardware.handler;

import com.doubao.hardware.config.IotMqConfig;
import com.doubao.hardware.config.IotMqttClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class MqttCallbackCustomReconnect extends IotMqttClient.BaseMqttCallback implements ApplicationContextAware {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final String logTitle = "MQTT回调: ";

    private ApplicationContext applicationContext;
    private final AtomicInteger reconnectAttempts = new AtomicInteger(0);
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    // 最大重连次数
    private static final int MAX_RECONNECT_ATTEMPTS = 10;
    // 重连基础间隔（秒）
    private static final int BASE_RECONNECT_DELAY = 5;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    private IotMqConfig getIotMqConfig() {
        return applicationContext.getBean(IotMqConfig.class);
    }

    @Override
    public void connectionLost(Throwable throwable) {
        logger.error(logTitle + "MQTT连接断开: {}", throwable.getMessage());

        // 如果超过最大重连次数，重置计数器
        if (reconnectAttempts.get() > MAX_RECONNECT_ATTEMPTS) {
            logger.warn(logTitle + "已达到最大重连次数，重置计数器");
            reconnectAttempts.set(0);
        }

        // 计算重连延迟（指数退避策略）
        int attempt = reconnectAttempts.incrementAndGet();
        int delay = Math.min(BASE_RECONNECT_DELAY * attempt, 60); // 最大延迟60秒

        logger.info(logTitle + "计划第{}次重连，将在{}秒后尝试", attempt, delay);

        // 安排重连任务
        scheduler.schedule(() -> {
            try {
                logger.info(logTitle + "正在尝试第{}次重连", attempt);
                IotMqttClient newClient = getIotMqConfig().getMqtt();

                if (newClient != null && newClient.isConnected()) {
                    logger.info(logTitle + "重连成功");
                    reconnectAttempts.set(0); // 重置重连计数器
                } else {
                    logger.error(logTitle + "重连失败");
                    // 重连失败，会再次触发connectionLost
                }
            } catch (Exception e) {
                logger.error(logTitle + "重连过程中发生错误: {}", e.getMessage(), e);
            }
        }, delay, TimeUnit.SECONDS);
    }

    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        logger.info(logTitle + "收到消息: topic={}, qos={}, retained={}, payload={}",
                topic,
                mqttMessage.getQos(),
                mqttMessage.isRetained(),
                new String(mqttMessage.getPayload()));
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        try {
            logger.debug(logTitle + "消息发送完成: messageId={}, topics={}",
                    token.getMessageId(),
                    String.join(",", token.getTopics()));
        } catch (Exception e) {
            logger.error(logTitle + "处理deliveryComplete回调时发生错误", e);
        }
    }
}